package com.ibeeking.found.org.cp.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.constants.GlobalConstant;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.org.cp.rest.service.IDepartmentService;
import com.ibeeking.found.org.service.common.dos.DepartmentDO;
import com.ibeeking.found.org.service.common.param.DepartmentParam;
import com.ibeeking.found.org.service.common.query.DepartmentQuery;
import com.ibeeking.found.org.service.common.vo.DepartmentTreeVO;
import com.ibeeking.found.org.service.common.vo.DepartmentVO;
import com.ibeeking.found.org.service.mapper.DepartmentMapper;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.TreeFastUtils;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.json.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName DepartmentServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-29 14:48
 **/
@Service
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, DepartmentDO> implements IDepartmentService {

    @Resource
    private DepartmentMapper departmentMapper;

    @Override
    public List<DepartmentVO> list(DepartmentQuery query) {
        List<DepartmentDO> entityDOS = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>()
                .eq(query.getId()!=null ,DepartmentDO::getId, query.getId())
                .eq(query.getParentId()!=null ,DepartmentDO::getParentId, query.getParentId())
                .eq(query.getLeaderId()!=null ,DepartmentDO::getLeaderId, query.getLeaderId())
                .eq(StringUtils.isNotEmpty(query.getCode()),DepartmentDO::getCode, query.getCode())
                .like(StringUtils.isNotEmpty(query.getName()),DepartmentDO::getName, query.getName())
                .orderByDesc(DepartmentDO::getCreateTime));
        return JsonUtils.jsonToList(entityDOS, DepartmentVO.class);
    }

    @Override
    public List<DepartmentTreeVO> listTree(DepartmentQuery query) {
        List<DepartmentDO> entityDOS = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>()
                .eq(query.getId()!=null ,DepartmentDO::getId, query.getId())
                .eq(query.getParentId()!=null ,DepartmentDO::getParentId, query.getParentId())
                .eq(query.getLeaderId()!=null ,DepartmentDO::getLeaderId, query.getLeaderId())
                .eq(StringUtils.isNotEmpty(query.getCode()),DepartmentDO::getCode, query.getCode())
                .like(StringUtils.isNotEmpty(query.getName()),DepartmentDO::getName, query.getName())
                .eq(query.getPublishStatus()!=null, DepartmentDO::getPublishStatus, query.getPublishStatus())
                .orderByDesc(DepartmentDO::getCreateTime));
        if (Collections3.isEmpty(entityDOS)) {
            return Collections3.emptyList();
        }
        List<Long> departmentIdS = entityDOS.parallelStream().map(DepartmentDO::getId).collect(Collectors.toList());
        if (null != query.getParentId()) {
            departmentIdS.add(query.getParentId());
        }
        //查询所有
        List<DepartmentDO> allDepartmentList = departmentMapper.selectList(new LambdaQueryWrapper<>(DepartmentDO.class)
                .eq(query.getPublishStatus()!=null, DepartmentDO::getPublishStatus, query.getPublishStatus())
                .orderByAsc(DepartmentDO::getSort)
                .orderByDesc(DepartmentDO::getCreateTime)
        );
        List<DepartmentTreeVO> allDepartmentTrees = JsonUtils.jsonToList(allDepartmentList, DepartmentTreeVO.class);
        List<Long> result = new ArrayList<>();
        TreeFastUtils.selectLongCidByPid(result, allDepartmentTrees, departmentIdS);
        result.addAll(departmentIdS);
        allDepartmentTrees = allDepartmentTrees.stream().filter(g -> result.contains(g.getId())).collect(Collectors.toList());
        if (null == query.getParentId()) {
            query.setParentId(GlobalConstant.PARENT_ID);
        }
        return TreeFastUtils.listToTree(allDepartmentTrees, query.getParentId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(DepartmentParam param) {
        this.checkUnique(param);
        DepartmentDO entityDO = BeanUtil.convertBean(param, DepartmentDO.class);
        entityDO.setId(IdGenerator.getId());
        entityDO.setCreateBy(UserUtils.getUserId());
        entityDO.setCreateTime(LocalDateTime.now());
        entityDO.setModifyTime(LocalDateTime.now());
        return departmentMapper.insert(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(DepartmentParam param) {
        this.checkUnique(param);
        DepartmentDO entityDO = BeanUtil.convertBean(param, DepartmentDO.class);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        return departmentMapper.updateById(entityDO) > 0;
    }

    @Override
    public DepartmentVO view(Long id) {
        DepartmentDO entityDO = departmentMapper.selectById(id);
        return BeanUtil.convertBeanByJson(entityDO, DepartmentVO.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status) {
        DepartmentDO entityDO = departmentMapper.selectById(id);

        entityDO.setPublishStatus(status);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        return departmentMapper.updateById(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        DepartmentDO entityDO = departmentMapper.selectById(id);
        if (entityDO == null) {
            return true;
        }
        PublishStatusEnum.statusCheckException(entityDO.getPublishStatus());
        //删除会员偏好关系表数据
        return departmentMapper.deleteById(id) > 0;
    }

    /**
     * 校验唯一性
     *
     * @param param
     */
    public void checkUnique(DepartmentParam param) {
        if (param == null) {
            throw new BusinessException("当前职位数据不存在!");
        }
        //code name确保等级唯一性
        LambdaQueryWrapper<DepartmentDO> queryWrapper = new LambdaQueryWrapper<DepartmentDO>()
                .ne(param.getId() != null, DepartmentDO::getId, param.getId())
                .eq(DepartmentDO::getName, param.getName());
        List<DepartmentDO> dos = departmentMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在同名的职位!");
        }
    }

}